home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / Filezilla Server / FileZilla_Server-0_9_41.exe / source / AdminSocket.cpp < prev    next >
C/C++ Source or Header  |  2011-11-06  |  10KB  |  440 lines

  1. // FileZilla Server - a Windows ftp server
  2.  
  3. // Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
  4.  
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9.  
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. // AdminSocket.cpp: Implementierung der Klasse CAdminSocket.
  20. //
  21. //////////////////////////////////////////////////////////////////////
  22.  
  23. #include "stdafx.h"
  24. #include "AdminSocket.h"
  25. #include "AdminInterface.h"
  26. #include "OptionTypes.h"
  27. #include "misc\md5.h"
  28. #include "iputils.h"
  29. #include "Options.h"
  30. #include "version.h"
  31.  
  32. #define BUFSIZE 4096
  33.  
  34. //////////////////////////////////////////////////////////////////////
  35. // Konstruktion/Destruktion
  36. //////////////////////////////////////////////////////////////////////
  37.  
  38. CAdminSocket::CAdminSocket(CAdminInterface *pAdminInterface)
  39. {
  40.     ASSERT(pAdminInterface);
  41.     m_pAdminInterface = pAdminInterface;
  42.     m_bStillNeedAuth = TRUE;
  43.  
  44.     m_pRecvBuffer = new unsigned char[BUFSIZE];
  45.     m_nRecvBufferLen = BUFSIZE;
  46.     m_nRecvBufferPos = 0;
  47.     
  48.     SYSTEMTIME sTime;
  49.     GetSystemTime(&sTime);
  50.     VERIFY(SystemTimeToFileTime(&sTime, &m_LastRecvTime));
  51. }
  52.  
  53. CAdminSocket::~CAdminSocket()
  54. {
  55.     for (std::list<t_data>::iterator iter=m_SendBuffer.begin(); iter!=m_SendBuffer.end(); iter++)
  56.         delete [] iter->pData;
  57.  
  58.     delete [] m_pRecvBuffer;
  59. }
  60.  
  61. BOOL CAdminSocket::Init()
  62. {
  63.     char *buffer = new char[100];
  64.     char *p = buffer;
  65.     strcpy(buffer, "FZS");
  66.     p += 3;
  67.  
  68.     *p++ = 0;
  69.     *p++ = 4;
  70.     memcpy(p, &SERVER_VERSION, 4);
  71.     p += 4;
  72.     
  73.     *p++ = 0;
  74.     *p++ = 4;
  75.  
  76.     memcpy(p, &PROTOCOL_VERSION, 4);
  77.     p+=4;
  78.  
  79.     COptions options;
  80.     CStdString pass = options.GetOption(OPTION_ADMINPASS);
  81.     CStdString peerAddress;
  82.     UINT port = 0;
  83.     if (GetPeerName(peerAddress, port) && IsLocalhost(peerAddress) && pass == _T(""))
  84.     {
  85.         BOOL res = Send(buffer, p-buffer) == p - buffer;
  86.         delete [] buffer;
  87.         if (!res)
  88.         {
  89.             Close();
  90.             return FALSE;
  91.         }
  92.         return FinishLogon();        
  93.     }
  94.     else
  95.     {
  96.         *p++ = 0;
  97.         
  98.         DWORD len = 20;
  99.         memcpy(p, &len, 4);
  100.         p += 4;
  101.  
  102.         *p++ = 0;
  103.         *p++ = 8;
  104.         
  105.         int i;
  106.         for (i = 0; i < 8; i++)
  107.         {
  108.             m_Nonce1[i] = (rand()*256)/(RAND_MAX+1);
  109.             *p++ = m_Nonce1[i];
  110.         }
  111.         
  112.         *p++ = 0;
  113.         *p++ = 8;
  114.         
  115.         for (i = 0; i < 8; i++)
  116.         {
  117.             m_Nonce2[i] = (rand()*256)/(RAND_MAX+1);
  118.             *p++ = m_Nonce2[i];
  119.         }
  120.     }
  121.  
  122.     int res = Send(buffer, p-buffer) == p-buffer;
  123.     delete [] buffer;
  124.     return res;
  125. }
  126.  
  127. BOOL CAdminSocket::SendCommand(int nType, int nID, const void *pData, int nDataLength)
  128. {
  129.     if (m_bStillNeedAuth)
  130.         return TRUE;
  131.  
  132.     t_data data;
  133.     data.pData = new unsigned char[nDataLength + 5];
  134.     *data.pData = nType;
  135.     *data.pData |= nID << 2;
  136.     data.dwOffset = 0;
  137.     memcpy(data.pData + 1, &nDataLength, 4);
  138.     if (pData)
  139.         memcpy(data.pData+5, pData, nDataLength);
  140.  
  141.     data.dwLength = nDataLength + 5;
  142.  
  143.     m_SendBuffer.push_back(data);
  144.     
  145.     do
  146.     {
  147.         data = m_SendBuffer.front();
  148.         m_SendBuffer.pop_front();
  149.         int nSent = Send(data.pData + data.dwOffset, data.dwLength - data.dwOffset);
  150.         if (!nSent)
  151.             return FALSE;
  152.         if (nSent == SOCKET_ERROR)
  153.         {
  154.             if (WSAGetLastError()!=WSAEWOULDBLOCK)
  155.                 return FALSE;
  156.             m_SendBuffer.push_front(data);
  157.             return TRUE;
  158.         }
  159.         
  160.         if ((unsigned int)nSent < (data.dwLength-data.dwOffset))
  161.         {
  162.             data.dwOffset += nSent;
  163.             m_SendBuffer.push_front(data);
  164.         }
  165.         else
  166.         {
  167.             delete [] data.pData;
  168.  
  169.             SYSTEMTIME sTime;
  170.             GetSystemTime(&sTime);
  171.             VERIFY(SystemTimeToFileTime(&sTime, &m_LastRecvTime));
  172.         }
  173.     } while (!m_SendBuffer.empty());
  174.  
  175.     return TRUE;
  176. }
  177.  
  178. void CAdminSocket::OnReceive(int nErrorCode)
  179. {
  180.     if (nErrorCode)
  181.     {
  182.         Close();
  183.         m_pAdminInterface->Remove(this);
  184.         return;
  185.     }
  186.     int numread = Receive(m_pRecvBuffer + m_nRecvBufferPos, m_nRecvBufferLen - m_nRecvBufferPos);
  187.     if (numread > 0)
  188.     {
  189.         SYSTEMTIME sTime;
  190.         GetSystemTime(&sTime);
  191.         VERIFY(SystemTimeToFileTime(&sTime, &m_LastRecvTime));
  192.  
  193.         m_nRecvBufferPos += numread;
  194.         if (m_nRecvBufferLen-m_nRecvBufferPos < (BUFSIZE/4))
  195.         {
  196.             unsigned char *tmp=m_pRecvBuffer;
  197.             m_nRecvBufferLen *= 2;
  198.             m_pRecvBuffer = new unsigned char[m_nRecvBufferLen];
  199.             memcpy(m_pRecvBuffer, tmp, m_nRecvBufferPos);
  200.             delete [] tmp;
  201.         }
  202.         int parseResult;
  203.         while ((parseResult = ParseRecvBuffer()) > 0);
  204.  
  205.         if (parseResult == -1)
  206.             return;
  207.     }
  208.     if (numread == 0)
  209.     {
  210.         if (ParseRecvBuffer() == -1)
  211.             return;
  212.         Close();
  213.         m_pAdminInterface->Remove(this);
  214.         return;
  215.     }
  216.     else if (numread == SOCKET_ERROR)
  217.     {
  218.         if (WSAGetLastError() != WSAEWOULDBLOCK)
  219.         {
  220.             if (ParseRecvBuffer() == -1)
  221.                 return;
  222.             Close();
  223.             m_pAdminInterface->Remove(this);
  224.             return;
  225.         }
  226.     }
  227.     while (ParseRecvBuffer() > 0);
  228. }
  229.  
  230. void CAdminSocket::OnSend(int nErrorCode)
  231. {
  232.     if (nErrorCode)
  233.     {
  234.         Close();
  235.         m_pAdminInterface->Remove(this);
  236.         return;
  237.     }
  238.  
  239.     while (!m_SendBuffer.empty())
  240.     {
  241.         t_data data=m_SendBuffer.front();
  242.         m_SendBuffer.pop_front();
  243.         int nSent = Send(data.pData+data.dwOffset, data.dwLength-data.dwOffset);
  244.         if (!nSent)
  245.         {
  246.             Close();
  247.             m_pAdminInterface->Remove(this);
  248.             return;
  249.         }
  250.         if (nSent == SOCKET_ERROR)
  251.         {
  252.             if (WSAGetLastError() != WSAEWOULDBLOCK)
  253.             {
  254.                 Close();
  255.                 m_pAdminInterface->Remove(this);
  256.             }
  257.             m_SendBuffer.push_front(data);
  258.             return;
  259.         }
  260.         
  261.         if ((unsigned int)nSent<(data.dwLength-data.dwOffset))
  262.         {
  263.             data.dwOffset+=nSent;
  264.             m_SendBuffer.push_front(data);
  265.         }
  266.         else
  267.             delete [] data.pData;
  268.     }
  269. }
  270.  
  271. int CAdminSocket::ParseRecvBuffer()
  272. {
  273.     if (m_nRecvBufferPos<5)
  274.         return 0;
  275.  
  276.     if ((m_pRecvBuffer[0]&0x03) != 0)
  277.     {
  278.         SendCommand(_T("Protocol error: Unknown command type, closing connection."), 1);
  279.         Close();
  280.         m_pAdminInterface->Remove(this);
  281.         return -1;
  282.     }
  283.     else
  284.     {
  285.         DWORD len;
  286.         memcpy(&len, m_pRecvBuffer+1, 4);
  287.         if (len > 0xFFFFFF)
  288.         {
  289.             SendCommand(_T("Protocol error: Invalid data length, closing connection."), 1);
  290.             Close();
  291.             m_pAdminInterface->Remove(this);
  292.             return -1;
  293.         }
  294.         if (m_nRecvBufferPos < len+5)
  295.             return 0;
  296.         else
  297.         {
  298.             int nID = (m_pRecvBuffer[0]&0x7C) >> 2;
  299.             if (m_bStillNeedAuth)
  300.             {
  301.                 if (nID)
  302.                 {
  303.                     SendCommand(_T("Protocol error: Not authenticated, closing connection."), 1);
  304.                     Close();
  305.                     m_pAdminInterface->Remove(this);
  306.                     return -1;
  307.                 }
  308.                 if (len != 16)
  309.                 {
  310.                     SendCommand(_T("Protocol error: Auth data len invalid, closing connection."), 1);
  311.                     Close();
  312.                     m_pAdminInterface->Remove(this);
  313.                     return -1;
  314.                 }
  315.                 MD5 md5;
  316.                 md5.update(m_Nonce1, 8);
  317.                 COptions options;
  318.                 CStdString pass = options.GetOption(OPTION_ADMINPASS);
  319.                 if (pass.GetLength() < 6)
  320.                 {
  321.                     SendCommand(_T("Protocol error: Server misconfigured, admin password not set correctly"), 1);
  322.                     Close();
  323.                     m_pAdminInterface->Remove(this);
  324.                     return -1;
  325.                 }
  326.                 char* utf8 = ConvToNetwork(pass);
  327.                 if (!utf8)
  328.                 {
  329.                     SendCommand(_T("Failed to convert password to UTF-8"), 1);
  330.                     Close();
  331.                     m_pAdminInterface->Remove(this);
  332.                     return -1;
  333.                 }
  334.                 md5.update((unsigned char *)utf8, strlen(utf8));
  335.                 delete [] utf8;
  336.                 md5.update(m_Nonce2, 8);
  337.                 md5.finalize();
  338.                 unsigned char *digest = md5.raw_digest();
  339.                 if (memcmp(m_pRecvBuffer + 5, digest, 16))
  340.                 {
  341.                     delete [] digest;
  342.                     SendCommand(_T("Protocol error: Auth failed, closing connection."), 1);
  343.                     Close();
  344.                     m_pAdminInterface->Remove(this);
  345.                     return -1;
  346.                 }
  347.                 delete [] digest;
  348.  
  349.                 FinishLogon();
  350.             }
  351.             else
  352.                 m_pAdminInterface->ProcessCommand(this, nID, m_pRecvBuffer+5, len);
  353.             memmove(m_pRecvBuffer, m_pRecvBuffer+len+5, m_nRecvBufferPos-len-5);
  354.             m_nRecvBufferPos-=len+5;
  355.         }
  356.     }
  357.     return 1;
  358. }
  359.  
  360. BOOL CAdminSocket::SendCommand(LPCTSTR pszCommand, int nTextType)
  361. {
  362.     DWORD nDataLength;
  363.     const char *utf8 = 0;
  364.  
  365.     if (!pszCommand)
  366.         nDataLength = 0;
  367.     else
  368.     {
  369.         utf8 = ConvToNetwork(pszCommand);
  370.         nDataLength = strlen(utf8) + 1;
  371.     }
  372.  
  373.     t_data data;
  374.     data.pData = new unsigned char[nDataLength + 5];
  375.     *data.pData = 2;
  376.     *data.pData |= 1 << 2;
  377.     data.dwOffset = 0;
  378.     memcpy(data.pData + 1, &nDataLength, 4);
  379.     *(data.pData+5) = nTextType;
  380.     if (utf8)
  381.         memcpy(reinterpret_cast<char *>(data.pData+6), utf8, nDataLength - 1);
  382.     delete [] utf8;
  383.  
  384.     data.dwLength = nDataLength + 5;
  385.  
  386.     m_SendBuffer.push_back(data);
  387.     
  388.     do 
  389.     {
  390.         data = m_SendBuffer.front();
  391.         m_SendBuffer.pop_front();
  392.         int nSent = Send(data.pData + data.dwOffset, data.dwLength - data.dwOffset);
  393.         if (!nSent)
  394.             return FALSE;
  395.         if (nSent == SOCKET_ERROR)
  396.         {
  397.             if (WSAGetLastError() != WSAEWOULDBLOCK)
  398.                 return FALSE;
  399.             m_SendBuffer.push_front(data);
  400.             return TRUE;
  401.         }
  402.         
  403.         if ((unsigned int)nSent < (data.dwLength - data.dwOffset))
  404.         {
  405.             data.dwOffset += nSent;
  406.             m_SendBuffer.push_front(data);
  407.         }
  408.         else
  409.             delete [] data.pData;
  410.     } while (!m_SendBuffer.empty());
  411.  
  412.     return TRUE;
  413. }
  414.  
  415. BOOL CAdminSocket::CheckForTimeout()
  416. {
  417.     SYSTEMTIME sTime;
  418.     FILETIME fTime;
  419.     GetSystemTime(&sTime);
  420.     VERIFY(SystemTimeToFileTime(&sTime, &fTime));
  421.     
  422.     _int64 LastRecvTime = ((_int64)m_LastRecvTime.dwHighDateTime << 32) + m_LastRecvTime.dwLowDateTime;
  423.     _int64 CurTime = ((_int64)fTime.dwHighDateTime << 32) + fTime.dwLowDateTime;
  424.  
  425.     if ((CurTime - LastRecvTime) > 600000000) // 60 seconds
  426.         return TRUE;
  427.  
  428.     return FALSE;
  429. }
  430.  
  431. BOOL CAdminSocket::FinishLogon()
  432. {
  433.     m_bStillNeedAuth = FALSE;
  434.  
  435.     //Logon successful
  436.     if (!SendCommand(1, 0, NULL, 0))
  437.         return FALSE;
  438.     return TRUE;
  439. }
  440.